package se.vgregion.icc.handlers;

import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import se.riv.itintegration.dependencies.response.v1.ObjectFactory;
import se.riv.itintegration.dependencies.response.v1.SimpleDependencyResponse;
import se.riv.itintegration.dependencies.v1.AbstractDependency;
import se.riv.itintegration.dependencies.v1.SimpleDependency;
import se.riv.itintegration.monitoring.pingforconfigurationresponder.v1.PingForConfigurationType;
import se.vgregion.icc.handlers.annotations.PingDependencyHandler;

/***
 * Implementation of PingHandler.
 * Handles pinging of simple/unspecified dependencies.
 * 
 * @author ricra2 & andan40
 * @see {@link se.vgregion.icc.handlers.PingHandler}
 * @see {@link se.riv.itintegration.dependencies.v1.SimpleDependency}
 * @see {@link se.vgregion.icc.handlers.annotations.PingDependencyHandler}
 */
@SuppressWarnings("rawtypes")
@PingDependencyHandler
public class SimplePingHandler implements PingHandler {
    private static final Logger LOG = LoggerFactory.getLogger(SimplePingHandler.class);

    private static final String PING_STATUS_RESPONDING = "RESPONDING";
    private static final String PING_STATUS_NOT_RESPONDING = "NOT RESPONDING";

    /***
     * {@inheritDoc}
     */
    @Override
    public String preformPingAndReturnResponse(AbstractDependency dependency, PingForConfigurationType parameters) {
        SimpleDependency simpleDependency = (SimpleDependency) dependency;
        ObjectFactory objectFactory = new ObjectFactory();

        SimpleDependencyResponse simpleDependencyResponse = objectFactory.createSimpleDependencyResponse();
        setSimpleDependencyResponseValue(simpleDependency, simpleDependencyResponse);

        if (isSimpleDependencyReachable(simpleDependency.getUrl())) {
            simpleDependencyResponse.setStatus(PING_STATUS_RESPONDING);
        } else {
            simpleDependencyResponse.setStatus(PING_STATUS_NOT_RESPONDING);
        }
        return marshal(simpleDependencyResponse);
    }

    /***
     * {@inheritDoc}
     * @return SimpleDependency.class
     */
    @Override
    public Class getHandledDependencyClass() {
        return SimpleDependency.class;
    }

    /***
     * {@inheritDoc}
     */
    @Override
    public String marshal(Object responseType) {
        String marshal = "";

        JAXBElement<SimpleDependencyResponse> jaxbSimpleDependencyResponse = null;
        if (responseType instanceof SimpleDependencyResponse) {
            SimpleDependencyResponse simpleDependencyResponse = (SimpleDependencyResponse) responseType;
            ObjectFactory objectFactory = new ObjectFactory();
            jaxbSimpleDependencyResponse = objectFactory.createSimpleDependencyResponse(simpleDependencyResponse);
        }

        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(SimpleDependencyResponse.class);
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            StringWriter stringWriter = new StringWriter();

            jaxbMarshaller.marshal(jaxbSimpleDependencyResponse, stringWriter);

            marshal = stringWriter.toString();

        } catch (Exception e) {
            LOG.error("Couldn't marshal the object " + responseType);
        }
        return marshal;
    }

    /***
     * Setting the name and resourceType on the simpleDependencyResponse from the simpleDependency.
     * @param simpleDependency
     * @param simpleDependencyResponse
     */
    private void setSimpleDependencyResponseValue(SimpleDependency simpleDependency,
        SimpleDependencyResponse simpleDependencyResponse) {

        simpleDependencyResponse.setName(simpleDependency.getName());
        simpleDependencyResponse.setResourceType(simpleDependency.getResourceType());
        simpleDependencyResponse.setUrl(simpleDependency.getUrl());
    }

    /***
     * Checks if the simple dependency is reachable.
     * 
     * @param uri address you want to ping.
     * @return true if ping was successful.
     */
    private boolean isSimpleDependencyReachable(String uri) {
        try {
            String cmdCommand = "";
            if (System.getProperty("os.name").startsWith("Windows")) {
                cmdCommand = "ping -n 1 " + uri;
            } else {
                cmdCommand = "ping -c 1 " + uri;
            }

            Process process = Runtime.getRuntime().exec(cmdCommand);
            process.waitFor();

            if (process.exitValue() == 0) {
                return true;
            }
            return false;

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}
